package org.huang.test;

import com.sun.net.httpserver.SimpleFileServer;
import org.huang.util.User;

import java.lang.invoke.MethodHandles;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import static java.util.stream.Collectors.*;

/**
 * @author hdu_huang
 * @since 2024/1/3 11:42
 *  JDK21 feature
 *  版本feature: <a href="https://segmentfault.com/a/1190000044238496">...</a>
 *  版本deprecated-list： <a href="https://cr.openjdk.org/~iris/se/21/latestSpec/api/deprecated-list.html">...</a>
 */
public class Feature {

    //! java16 成员内部类/局部内部类/匿名内部类 可以拥有static变量和方法
    class B{
        static int a;
        public static void test(){
            class C{ static int c;}
            record A(int a) {static int c;}
        }
    }

    //java16 record类
    //Call to 'this()/super()' must be first statement in constructor body, 仅仅是Java规范的要求
    record X(int age, String name){ }

    //! 密封类 Java17   关键字sealed,non-sealed,permits   子类必须final或者non-sealed
    abstract sealed static class Shape permits Circle, Square { }
    public static final class Circle extends Shape { }
    public static non-sealed class Square extends Shape { }

    /**
     *
     * java9:模块化[classloader] 接口[default/static/private/private static] 弃用CMS 不变集合(of)  String[byte] try-with-resources  VarHandler
     * java10：var  不变集合(copyOf)  *G1的并行完全GC(JEP 307)*  Collectors不变集合
     *
     * java11(LTS)： Http2 lambda-var   直接运行(java H.java)  TLS1.3(重磅)  ZGC(预览)  移除[JMC,Thread.(destroy), Unsafe.defineClass]
     * Flight Recorder免费   完全支持容器
     *
     * java12: G1的可中断mixed GC(JEP 344)  Collectors.teeing(T)  String[transform]
     * java13: switch表达式(Preview)   Text Blocks (Preview)
     * java14: instanceof模式匹配(预览) Records(预览)  switch表达式[转正]  移除CMS  G1的NUMA内存分配优化(JEP 307)
     * java15: Sealed Classes(Preview)[密封类]  Text Blocks[转正]  Shenandoah、ZGC[转正]  Hidden Classes(隐藏类)  移除[Unsafe.defineAnonymousClass]
     * java16: instanceof模式匹配[转正]  Record[转正]  并发ZGC  jpackage  Stream[toList/mapMulti]
     *
     * java17(LTS) 密封类[转正]  switch Pattern matching(Preview)   HexFormat
     * 增强TreeMap[java17修复] (TreeMap没有对putIfAbsent、computeIfAbsent、computeIfPresent、compute的专门实现。默认实现经常导致两次树遍历)
     *
     * java18 默认UTF-8 jwebserver(SimpleFileServer)  finalize标记删除
     * java19  Virtual Threads (Preview)  Record Patterns(Preview)    Thread.threadId取代getId()
     * java20  无
     *
     * java21(LTS)  1.顺序集合  2.Record Patterns(转正)  3.Pattern Matching for switch(转正)  4.Virtual Threads(转正)  5.分代ZGC
     * 1.String Templates(Preview)  2.Unnamed Patterns and Variables (Preview) 3.Unnamed Classes and Instance Main Methods (Preview)
     * 4.Scoped Values (Preview)    5.Structured Concurrency (Preview)
     * StructuredTaskScope 结构化并发和虚拟线程  ScopedValue
     *
     * 隐藏类[Lookup#defineHiddenClass]  defineAnonymousClass  lambda生成的类   [jpackage打包]
     * javac --enable-preview --release 13 Example.java
     * java --enable-preview Example
     */

    //major  feature
    // java11  module, try-with-resources, VarHandler, var, 不变集合(of, copyOf) HttpClient2.0
    // java17  switch表达式(lambda)  Text Blocks  密封类 [jpackage打包]   instanceof模式匹配  Record
    // java21  Record模式匹配  switch模式匹配  顺序集合  虚拟线程
    // String Templates(Preview)  Scoped Values (Preview) Structured Concurrency (Preview)
    // StructuredTaskScope, ScopedValue  结构化并发和作用域值
    public static void main(String[] args) {

        B.a = 10;

        testVariable();
        testCollection();
        testMap();
        testConcurrentMap();
        testStream();
        testString();
        testCollectors();
        testOptional();


        //CompletableFuture API
        //java11 Files 读写文件增强   java17 RandomGenerator  Collections   HashMap.newHashMap

        String separator = System.lineSeparator();

        //java18 getId deprecated
        long threadId = Thread.currentThread().threadId();

        var list = List.of("a", "b", "c");
        list.forEach(System.out::println);

        var str = "hello world!";

        ////java21  indexOf splitWithDelimiters
        int wo = str.indexOf("wo", 1, 5);

        System.out.println(str);

        Thread.Builder.OfVirtual virtual = Thread.ofVirtual();

        virtual.start(() -> System.out.println("Hello"));

        var arr = new int[]{1, 5, 3, 4, 2};

        System.out.println(Arrays.toString(arr));

        //SequencedCollection SequencedSet SequencedMap
        System.out.println(List.of(1, 2, 3));

        var user = new User(10, 23,"黄");

        int age = user.age();

        System.out.println(user);


        record LocalRecord(int a, int b) { }

        X x = new X(1, "name");


        // java15 text blocks(文本块)   \转义序列表示为同一行字符串   """你好""" 不换行的写法是不支持的
        var string = """
            你好吗？ %s \
            i am fine!
                """;

        string = string.indent(2).formatted(x);
        System.err.println(string);

        //testJavaWebServer();
        testSequencedCollection();
        testRecordPatterns(x);
        testSwitchPatterns(null, null);

        testStringTemplates();

    }

    //javac --enable-preview --release 21 Example.java
    // java --enable-preview Example
    public static void testStringTemplates(){

        //Processor<String, RuntimeException> STR         // 用来拼接字符串
        //Processor<StringTemplate, RuntimeException> RAW // 原样返回StringTemplate

        var name = "world";
        //var str = STR."hello \{name}";

        //var st1 = StringTemplate.of("hello {name}");
        //List<String> fragments = st1.fragments();
        //String interpolate = st1.interpolate();

    }

    //  java21简单HttpServer [底层是java6 com.sun.net.httpserver.HttpServer]
    public static void testJavaWebServer(){

        var addr = new InetSocketAddress(80);
        var server = SimpleFileServer.createFileServer(addr, Path.of("E:\\other\\blog\\public"), SimpleFileServer.OutputLevel.INFO);
        server.start();
    }

    // java21 顺序集合
    public static void testSequencedCollection(){

        SequencedCollection<Integer> list = new ArrayList<>(List.of(1, 2, 3, 4, 5));
        list.removeFirst();
        list.removeLast();
        list.addFirst(0);
        list.addLast(6);
        list.add(7);

        SequencedSet<Integer> set = new LinkedHashSet<>(List.of(1, 2, 3, 4, 5));
        set.addFirst(0);
        set.removeLast();

        SequencedMap<Integer, Integer> map = new LinkedHashMap<>(Map.of(1,1, 2,2, 3,3));
        map.putFirst(0, 0);
        map.putLast(4, 4);

        System.out.println(set + " " + map);
    }

    //java21 Record模式匹配, 还可以用在switch语句和表达式中
    public static void testRecordPatterns(Object obj){

        //Record解构
        if (obj instanceof User(int id, int age, String name)) {
            System.out.println("Record解构: " + id + ":" + age + ":" + name);
        }

        //java16 instanceof模式匹配
        if (obj instanceof X x) {
            System.out.println("instanceof模式匹配" + x);
        }

    }

    //java21 switch模式匹配(case null)    可以匹配数值和类型  yield只会跳出当前的switch块
    public static void testSwitchPatterns(Object obj, Integer integer){

        //switch表达式有返回值 [break不能用在switch表达式中]
        int i = switch (obj) {
            case null -> -1; //没有此会NPE
            case User(int id, int age, String name) -> {
                System.out.println("Record解构: " + id + ":" + age + ":" + name);
                yield 1;

            }
            case X x -> {
                System.out.println("instanceof模式匹配" + x);
                yield 2;
            }
            default -> 0;
        };

        //switch语句没有返回值,  不允许混用 -> 和 [: break]
        switch(integer) {
            case null -> {} //没有此会NPE
            case 1, 2, 3 -> System.out.println("1,2,3");
            case 4, 5, 6 -> System.out.println("4,5,6");
            default -> System.out.println("default");
        }
    }


    /**
     * 它局限于: 1.有初始化值的局部变量 2.增强for循环中的索引  3.传统for循环中声明的局部变量
     * 局部变量类型推断和for循环  [不能声明变量] var a; a = 1 错误
     */
    public static void testVariable() {

        var integers = List.of(1, 2, 3, 4, 5, 6);

        integers.forEach((var integer) -> {
            var i = 10;
        });

        for (var i : integers) {
        }

        var ints = new int[]{0, 1, 2}; // var ints = {0, 1, 2} 不行
    }

    //! -------------------------API 增强------------------------------------------------------

    //Collection 8: removeIf(filter) stream spliterator/parallelStream   11: toArray
    //List 8: replaceAll(map) sort(comparator)  of  9: of  10 copyOf
    //Set 8: replaceAll(map)   of  9: of  10 copyOf
    public static void testCollection() {

        ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 5, 3, null, 4, 1, 2, null));
        list.stream().filter(Objects::nonNull).map(e -> e * 3).count();

        list.removeIf(Objects::isNull);
        list.replaceAll(integer -> 2 * integer);
        list.sort(Comparator.naturalOrder());

        List<Integer> list1 = List.of(1, 3, 4, 5, 2);
        List<Integer> list2 = List.copyOf(list1); //list1 == list2

        Set<Integer> set1 = Set.of(1, 3, 5, 7, 2);
        Set<Integer> set2 = Set.of(1, 3, 5, 4, 6);
    }

    //Map.Entry 8: comparingByKey comparingByValue   17:copyOf
    //Map 8: getOrDefault forEach replaceAll putIfAbsent(*) remove(key, value)  replace  compute computeIfAbsent(*) computeIfPresent merge(*)
    //Map 9:of  ofEntries  entry  10:copyOf  [key-value都不能是null]
    //HashMap 19: newHashMap
    public static void testMap() {

        Comparator<Integer> compare = Integer::compare;
        Comparator<Map.Entry<String, String>> comparator = Map.Entry.comparingByKey();
        Comparator<Map.Entry<Integer, Object>> entryComparator = Map.Entry.comparingByKey(compare);

        Map.Entry<Integer, String> hello = Map.entry(10, "hello");
        Map<Integer, String> integerStringMap = Map.of(1, "1", 2, "2", 3, "3");
        Map<Integer, String> copyOf = Map.copyOf(integerStringMap);

        HashMap<Integer, String> objectObjectHashMap = HashMap.<Integer, String>newHashMap(16);

        //major:Java8 Map方法
        //只有Hashtable的merge.value可以为null   /compute merge [BiFunction返回是null则删除元素]
        Map<String, String> mergeMap = new Hashtable<>();
        mergeMap.put("a", "a");
        mergeMap.put("b", "b");
        mergeMap.merge("a", null, (s, s2) -> null);//删除a

        String orDefault = mergeMap.getOrDefault("a", "c");
        mergeMap.forEach((key, value) -> {});
        mergeMap.replaceAll((key, value) -> key + value);

        String replace = mergeMap.replace("a", "b"); //replace[]
        boolean isReplace = mergeMap.replace("a", "b", "a"); //替换成功则返回true
        boolean remove = mergeMap.remove("a", "b"); //remove成功则返回true

        //返回旧值 如果是null则表示插入成功
        String s = mergeMap.putIfAbsent("a", "c");//s=null


        Map<Integer, Integer> hashMap = new HashMap<>(Map.of(1,1, 2,2,3,3));
        hashMap.put(3, null);
        hashMap.put(null, 4);

        //当putIfAbsent返回null表示插入成功[返回旧值]
        Integer integer = hashMap.putIfAbsent(null, null);

        //key存在 value=null也执行
        Integer computeIfAbsent = hashMap.computeIfAbsent(3, integer1 -> 3);
        Integer compute = hashMap.compute(null, (s1, s2) -> null);
        Integer integer1 = hashMap.computeIfPresent(1, Integer::sum);

        //当key不存在或value=null, 添加[不执行mergeFunction]  当key存在merge.value不能是null
        Integer merge = hashMap.merge(5, 4, Integer::sum);

        // System.out.println(hashMap);
    }

    //8:mappingCount[替代size]  newKeySet(*)  forEach、forEachKey、forEachValue、forEachEntry
    // search、searchKeys、searchValues、searchEntries  reduce、reduceKeys、reduceValues、reduceEntries
    public static void testConcurrentMap() {
        ConcurrentHashMap<Integer, String> chm = new ConcurrentHashMap<>();

        for (int i = 0; i < 10_000; i++) {
            chm.put(i, i + "");
        }
        {int a = 3;}

        chm.forEach(4, (key,value) -> {

        });

        //相当于find [断路]  fork-join
        Integer search = chm.search(4, (integer, s) -> {
            if ((integer + 1) % 114 == 0) { //113 1025...
                return integer;
            }
            return null;
        });

        //线程安全的set
        var set = ConcurrentHashMap.newKeySet(10);
        set.add(10);


        var reduce = chm.reduce(10, (integer, s) -> integer, (s, s2) -> s + s2);

    }


    //8 join[*]
    //9 chars  codePoints
    //11 repeat   lines[*]  isBlank stripTrailing  stripLeading  strip
    //12 describeConstable-resolveConstantDesc(返回自己)  transform[*]  indent(缩进)
    //15 formatted  translateEscapes  stripIndent(清除缩进)
    public static void testString() {

        String template = """
                do you know that i love %s!
                i hate hec.
                what happened!
                """;

        String string = "hello world!";
        List<String> lists = List.of("a", "b", "c");
        String join = String.join(".", lists);

        ArrayList<Character> chars = string.chars().mapToObj(integer -> (char) integer).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

        String repeat = string.repeat(2);
        String strip = "  mmm  ".strip(); //去除字符串前后的全角和半角空白字符

        Stream<String> lines = template.lines();
        List<String> strings = lines.toList();

        boolean equals = string.resolveConstantDesc(MethodHandles.lookup()).equals(string); //返回自己 true

        String indent = template.indent(2);

        //major:注意split, 丢弃尾随的空字符串   @see split(String regex, int limit)
        ArrayList<String> transform = "1,2,3,,".transform(s -> {
            String[] split = s.split(",");
            return new ArrayList<>(Arrays.asList(split));
        });

        String liYun = template.formatted("liYun");
    }

    //9 iterate  takeWhile  dropWhile [如果没有排序, 行为不确定]  ofNullable
    //16 [toList]  mapMulti mapMultiToInt  mapMultiToLong  mapMultiToDouble
    public static void testStream() {

        var integers = List.of(1, 3, 7, 2, 5, 4, 1);

        //integer++ 不行, 当Predicate(hasNext) false 终止
        Stream<Integer> iterate = Stream.iterate(1, integer -> integer <= 100, integer -> integer + 1);
        List<Integer> list = iterate.limit(10).toList();  //[1, 10]

        Stream<Integer> stream = integers.stream();

        //相当于 filter + map 可以增加减少元素  flatMap
        List<Object> objects = list.stream().mapMulti((integer, consumer) -> {
            if (integer > 5) {
                consumer.accept(integer);
            }
        }).toList();

        //major takeWhile/dropWhile 如果没有排序, 行为不确定
        var integers1 = stream.sorted().takeWhile(integer -> integer < 4).toList();

    }

    //9: flatMapping filtering
    //10: toUnmodifiableList toUnmodifiableSet toUnmodifiableMap
    //12: teeing(T)
    public static void testCollectors() {

        var integers = List.of(1, 3, 7, 2, 5, 4, 1);

        //teeing (collector1, collector2 -> merger)    collector1, collector2 -> collector3
        Long average = integers.stream().collect(teeing(summingInt(Integer::intValue), counting(), (sum, count) -> sum / count)); //3

        integers.stream().collect(teeing(mapping(i1 -> i1 * 2, filtering(i1 -> i1 > 4, counting())), summingInt(Integer::intValue), (sum, count) -> sum / count));

        Map<Integer, Integer> map = integers.stream().collect(toUnmodifiableMap(integer -> integer, integer -> integer * 2, (oldVal, currVal) -> oldVal));

        // log.info("average = {}", average);

    }

    //8:empty of ofNullable get isPresent ifPresent(*) filter map flatMap orElse orElseGet  orElseThrow
    //9:ifPresentOrElse   or  stream
    //10:orElseThrow
    //11:isEmpty
    public static void testOptional() {

        Optional<String> opt = Optional.of("hello");
        Optional.ofNullable(null);

        Optional<String> empty = Optional.empty();

        boolean present = opt.isPresent(); //是否存在 true
        boolean empty1 = opt.isEmpty(); //是否是空 false

        empty.map(String::isEmpty).orElse(false);

        long count = empty.stream().map(String::length).count();

        String s = empty.orElse("jdk");

    }


}